{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7911df20-e4a1-4471-a05f-98d85199bdca",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1cf4a4f5-da09-4b74-8609-a3eeb98fe767",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_208051/154769409.py:15: FutureWarning: 'S' is deprecated and will be removed in a future version, please use 's' instead.\n",
      "  \"timestamp\": pd.date_range(\"2025-06-01 00:00:00\", periods=num_records, freq=\"30S\"),\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "import matplotlib.pyplot as plt\n",
    "from datetime import datetime\n",
    "\n",
    "# ==== 1. 模拟数据集（模拟10辆车7天的行驶数据） ====\n",
    "# 数据生成逻辑：每30秒采集一次速度、加速度、刹车力等指标\n",
    "# 注：真实场景中数据来自车载TBOX终端\n",
    "np.random.seed(42)\n",
    "num_records = 20160  # 10辆车 * 7天 * 288条/天（30秒间隔）\n",
    "data = {\n",
    "    \"vehicle_id\": np.repeat([f\"V{str(i).zfill(3)}\" for i in range(1, 11)], 2016),\n",
    "    \"timestamp\": pd.date_range(\"2025-06-01 00:00:00\", periods=num_records, freq=\"30S\"),\n",
    "    \"speed\": np.clip(np.random.normal(60, 20, num_records), 0, 120),  # 限制速度范围（0-120km/h）\n",
    "    \"acceleration\": np.random.normal(0, 1.5, num_records),          # 加速度（单位：m/s²）\n",
    "    \"brake_force\": np.random.exponential(0.5, num_records),         # 刹车力度（无量纲，范围0-5）\n",
    "    \"driver_id\": np.random.choice([\"D001\", \"D002\", \"D003\", \"D004\"], num_records)\n",
    "}\n",
    "df = pd.DataFrame(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "211c7d03-b9ce-4520-b7e9-6ef59c39ce76",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>vehicle_id</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>speed</th>\n",
       "      <th>acceleration</th>\n",
       "      <th>brake_force</th>\n",
       "      <th>driver_id</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>V001</td>\n",
       "      <td>2025-06-01 00:00:00</td>\n",
       "      <td>69.934283</td>\n",
       "      <td>0.519220</td>\n",
       "      <td>0.150346</td>\n",
       "      <td>D004</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>V001</td>\n",
       "      <td>2025-06-01 00:00:30</td>\n",
       "      <td>57.234714</td>\n",
       "      <td>-1.164815</td>\n",
       "      <td>0.066056</td>\n",
       "      <td>D003</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>V001</td>\n",
       "      <td>2025-06-01 00:01:00</td>\n",
       "      <td>72.953771</td>\n",
       "      <td>1.119592</td>\n",
       "      <td>1.481727</td>\n",
       "      <td>D004</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>V001</td>\n",
       "      <td>2025-06-01 00:01:30</td>\n",
       "      <td>90.460597</td>\n",
       "      <td>0.397992</td>\n",
       "      <td>0.609853</td>\n",
       "      <td>D002</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>V001</td>\n",
       "      <td>2025-06-01 00:02:00</td>\n",
       "      <td>55.316933</td>\n",
       "      <td>-0.510593</td>\n",
       "      <td>0.097432</td>\n",
       "      <td>D002</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20155</th>\n",
       "      <td>V010</td>\n",
       "      <td>2025-06-07 23:57:30</td>\n",
       "      <td>82.270427</td>\n",
       "      <td>-1.247330</td>\n",
       "      <td>0.516653</td>\n",
       "      <td>D002</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20156</th>\n",
       "      <td>V010</td>\n",
       "      <td>2025-06-07 23:58:00</td>\n",
       "      <td>47.073654</td>\n",
       "      <td>-0.508878</td>\n",
       "      <td>1.716646</td>\n",
       "      <td>D002</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20157</th>\n",
       "      <td>V010</td>\n",
       "      <td>2025-06-07 23:58:30</td>\n",
       "      <td>38.560807</td>\n",
       "      <td>1.157293</td>\n",
       "      <td>1.021269</td>\n",
       "      <td>D001</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20158</th>\n",
       "      <td>V010</td>\n",
       "      <td>2025-06-07 23:59:00</td>\n",
       "      <td>56.129085</td>\n",
       "      <td>1.883631</td>\n",
       "      <td>0.751100</td>\n",
       "      <td>D003</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20159</th>\n",
       "      <td>V010</td>\n",
       "      <td>2025-06-07 23:59:30</td>\n",
       "      <td>57.907068</td>\n",
       "      <td>0.256444</td>\n",
       "      <td>0.578409</td>\n",
       "      <td>D004</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>20160 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      vehicle_id           timestamp      speed  acceleration  brake_force  \\\n",
       "0           V001 2025-06-01 00:00:00  69.934283      0.519220     0.150346   \n",
       "1           V001 2025-06-01 00:00:30  57.234714     -1.164815     0.066056   \n",
       "2           V001 2025-06-01 00:01:00  72.953771      1.119592     1.481727   \n",
       "3           V001 2025-06-01 00:01:30  90.460597      0.397992     0.609853   \n",
       "4           V001 2025-06-01 00:02:00  55.316933     -0.510593     0.097432   \n",
       "...          ...                 ...        ...           ...          ...   \n",
       "20155       V010 2025-06-07 23:57:30  82.270427     -1.247330     0.516653   \n",
       "20156       V010 2025-06-07 23:58:00  47.073654     -0.508878     1.716646   \n",
       "20157       V010 2025-06-07 23:58:30  38.560807      1.157293     1.021269   \n",
       "20158       V010 2025-06-07 23:59:00  56.129085      1.883631     0.751100   \n",
       "20159       V010 2025-06-07 23:59:30  57.907068      0.256444     0.578409   \n",
       "\n",
       "      driver_id  \n",
       "0          D004  \n",
       "1          D003  \n",
       "2          D004  \n",
       "3          D002  \n",
       "4          D002  \n",
       "...         ...  \n",
       "20155      D002  \n",
       "20156      D002  \n",
       "20157      D001  \n",
       "20158      D003  \n",
       "20159      D004  \n",
       "\n",
       "[20160 rows x 6 columns]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3d4eb504-3943-4690-8317-e58b127e9cfb",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_208051/94405918.py:7: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"hour\"] = df[\"timestamp\"].dt.hour\n",
      "/tmp/ipykernel_208051/94405918.py:8: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"is_night\"] = np.where((df[\"hour\"] >= 22) | (df[\"hour\"] <= 5), 1, 0)  # 夜间驾驶标记\n",
      "/tmp/ipykernel_208051/94405918.py:10: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"drive_duration\"] = df.groupby(\"driver_id\")[\"timestamp\"].diff().dt.total_seconds() / 60\n",
      "/tmp/ipykernel_208051/94405918.py:17: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"hard_accel\"] = np.where(df[\"acceleration\"] > 2.5, 1, 0)\n",
      "/tmp/ipykernel_208051/94405918.py:18: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"hard_brake\"] = np.where((df[\"acceleration\"] < -2.5) | (df[\"brake_force\"] > 3.5), 1, 0)\n",
      "/tmp/ipykernel_208051/94405918.py:19: SettingWithCopyWarning: \n",
      "A value is trying to be set on a copy of a slice from a DataFrame.\n",
      "Try using .loc[row_indexer,col_indexer] = value instead\n",
      "\n",
      "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
      "  df[\"fatigue_drive\"] = np.where((df[\"drive_duration\"].fillna(0) > 240) & (df[\"is_night\"] == 1), 1, 0)\n"
     ]
    }
   ],
   "source": [
    "# ==== 2. 数据预处理 ====\n",
    "# 目标：清洗异常值，提取时间特征，计算连续驾驶时长\n",
    "# 规则：加速度绝对值>3.5 m/s²或刹车力>5视为异常（参考行业标准）\n",
    "df = df[(df[\"acceleration\"].abs() <= 3.5) & (df[\"brake_force\"] <= 5)]\n",
    "\n",
    "# 时间特征工程：标记夜间驾驶（22:00-5:00）和连续驾驶时长\n",
    "df[\"hour\"] = df[\"timestamp\"].dt.hour\n",
    "df[\"is_night\"] = np.where((df[\"hour\"] >= 22) | (df[\"hour\"] <= 5), 1, 0)  # 夜间驾驶标记\n",
    "# 计算连续驾驶时长（单位：分钟），用于疲劳驾驶判定\n",
    "df[\"drive_duration\"] = df.groupby(\"driver_id\")[\"timestamp\"].diff().dt.total_seconds() / 60\n",
    "\n",
    "# ==== 3. 高风险行为特征工程 ====\n",
    "# 业务逻辑定义（基于保险公司事故报告）：\n",
    "#   - 急加速：加速度 > 2.5 m/s²（易引发追尾）\n",
    "#   - 急刹车：加速度 < -2.5 m/s² 或 刹车力 > 3.5（轮胎磨损+事故风险）\n",
    "#   - 疲劳驾驶：夜间连续驾驶 > 4小时（事故概率提升300%）\n",
    "df[\"hard_accel\"] = np.where(df[\"acceleration\"] > 2.5, 1, 0)\n",
    "df[\"hard_brake\"] = np.where((df[\"acceleration\"] < -2.5) | (df[\"brake_force\"] > 3.5), 1, 0)\n",
    "df[\"fatigue_drive\"] = np.where((df[\"drive_duration\"].fillna(0) > 240) & (df[\"is_night\"] == 1), 1, 0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "623c9aa8-ec21-4924-b4f2-a91b9ee651ae",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "763bf25f-d6b1-4517-bc9a-0a67924bc950",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "364f5d3a-b383-48b7-837f-4448c7fa2e7a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
